﻿using JBeamLibrary.Tools;
using JBeamLibrary.Types;
using JBeamLibrary.VehicleParts.Collections;
using JBeamLibrary.VehicleParts.Elements;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JBeamLibrary.VehicleParts.Interfaces;

namespace JBeamLibrary.VehicleParts.Groups
{
    public class InternalCameras : IVehicleGroup<InternalCamera>
    {
        #region Fields

        private readonly Dictionary<int, float> _nodeWeightList = new Dictionary<int, float>();
        private readonly Dictionary<int, bool> _selfCollisionList = new Dictionary<int, bool>();
        private readonly Dictionary<int, bool> _collisionList = new Dictionary<int, bool>();
        private readonly Dictionary<int, long> _beamStrengthList = new Dictionary<int, long>();
        private readonly Dictionary<int, long> _beamSpringList = new Dictionary<int, long>();
        private readonly Dictionary<int, long> _beamDampList = new Dictionary<int, long>();
        private readonly Dictionary<int, long> _beamDeformList = new Dictionary<int, long>();
        private readonly Dictionary<int, float> _beamPrecompressionList = new Dictionary<int, float>();
        private readonly Dictionary<int, float> _beamLongBoundList = new Dictionary<int, float>();
        private readonly Dictionary<int, float> _beamShortBoundList = new Dictionary<int, float>();
        private readonly Dictionary<int, long> _beamLimitSpringList = new Dictionary<int, long>();
        private readonly Dictionary<int, long> _beamLimitDampList = new Dictionary<int, long>();
        private readonly InternalCameraCollection _internalCameraCollection = new InternalCameraCollection();

        #endregion

        #region Indexers

        /// <summary>Gets the internal camera at the specified index</summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public InternalCamera this[int index]
        {
            get
            {
                if (Collection.Count == 0)
                    return null;
                if (index < 0 || index >= Collection.Count)
                    return null;
                return Collection[index];
            }
        }

        /// <summary>Gets the internal camera with the specified offset</summary>
        /// <param name="offset"></param>
        /// <returns></returns>
        public InternalCamera this[Float3 offset]
        {
            get { return Collection.FirstOrDefault(cam => cam.Offset.Equals(offset)); }
        }

        #endregion

        #region Properties

        public Dictionary<int, float> NodeWeightList
        {
            get { return _nodeWeightList; }
        }

        public Dictionary<int, bool> SelfCollisionList
        {
            get { return _selfCollisionList; }
        }

        public Dictionary<int, bool> CollisionList
        {
            get { return _collisionList; }
        }

        public Dictionary<int, long> BeamStrengthList
        {
            get { return _beamStrengthList; }
        }

        public Dictionary<int, long> BeamSpringList
        {
            get { return _beamSpringList; }
        }

        public Dictionary<int, long> BeamDampList
        {
            get { return _beamDampList; }
        }

        public Dictionary<int, long> BeamDeformList
        {
            get { return _beamDeformList; }
        }

        public Dictionary<int, float> BeamPrecompressionList
        {
            get { return _beamPrecompressionList; }
        }

        public Dictionary<int, float> BeamLongBoundList
        {
            get { return _beamLongBoundList; }
        }

        public Dictionary<int, float> BeamShortBoundList
        {
            get { return _beamShortBoundList; }
        }

        public Dictionary<int, long> BeamLimitSpringList
        {
            get { return _beamLimitSpringList; }
        }

        public Dictionary<int, long> BeamLimitDampList
        {
            get { return _beamLimitDampList; }
        }

        public InternalCameraCollection Collection
        {
            get { return _internalCameraCollection; }
        }

        public IVehicleGroupCollection<InternalCamera> GroupCollection
        {
            get { return Collection; }
        }

        public int Count
        {
            get { return _internalCameraCollection.Count; }
        }

        public bool IsEmpty
        {
            get
            {
                return GroupHelper.GetPropertyLists(this).All(list => list.Count == 0) && Collection.Count == 0;
            }
        }

        #endregion

        #region Methods

        public void SetElementValue(int index, string propName, object value)
        {
            var elem = Collection[index];
            var prop = elem.GetType().GetProperty(propName);
            prop.SetValue(elem, value);
        }

        public object GetElementValue(int index, string propName)
        {
            var elem = Collection[index];
            var prop = elem.GetType().GetProperty(propName);
            return prop.GetValue(elem);
        }

        public IEnumerable<KeyValuePair<string, object>> GetElementValues(int index)
        {
            var elem = Collection[index];
            var props = elem.GetType().GetProperties();
            return props.Select(prop => new KeyValuePair<string, object>(prop.Name, prop.GetValue(elem))).AsEnumerable();
        }

        #endregion
    }
}
